/**
 @file ctc_pdu_cli.c

 @date 2020-07-09

 @version v2.0

---file comments----
*/

/****************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_cli.h"
#include "ctc_cli_common.h"
#include "api/include/ctcs_api.h"
#include "ctc_common.h"
#include "ctc_pdu.h"
#include "ctc_pdu_cli.h"


CTC_CLI(ctc_cli_asw_pdu_l2_classify_l2pdu_by_macda,
        ctc_cli_asw_pdu_l2_classify_l2pdu_by_macda_cmd,
        "pdu l2pdu classify macda-48bit index INDEX macda MACDA",
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Classify pdu based on type",
        "Base on 48bit macda",
        "Entry index",
        CTC_CLI_L2PDU_MACDA_48BIT_ENTRY_INDEX,
        CTC_CLI_MAC_DESC,
        CTC_CLI_MAC_FORMAT)
{
    ctc_pdu_l2pdu_key_t entry;
    uint8 index = 0;
    int32 ret = 0;
    ctc_pdu_l2pdu_type_t l2pdu_type;

    sal_memset(&entry, 0, sizeof(ctc_pdu_l2pdu_key_t));
    l2pdu_type = CTC_PDU_L2PDU_TYPE_MACDA;

    CTC_CLI_GET_UINT8_RANGE("index", index, argv[0], 0, CTC_MAX_UINT8_VALUE);

    CTC_CLI_GET_MAC_ADDRESS("dest mac address", entry.l2pdu_by_mac.mac, argv[1]);

    ret = ctcs_l2pdu_classify_l2pdu(g_api_lchip, l2pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}


CTC_CLI(ctc_cli_asw_pdu_show_l2_classify_l2pdu_by_macda,
        ctc_cli_asw_pdu_show_l2_classify_l2pdu_by_macda_cmd,
        "show pdu l2pdu classify macda-48bit index INDEX",
        CTC_CLI_SHOW_STR,
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Classify pdu based on type",
        "Base on 48bit macda",
        "Entry index",
        CTC_CLI_L2PDU_MACDA_48BIT_ENTRY_INDEX)
{
    ctc_pdu_l2pdu_type_t l2pdu_type;
    ctc_pdu_l2pdu_key_t entry;
    uint8 index = 0;
    int32 ret = 0;

    sal_memset(&entry, 0, sizeof(ctc_pdu_l2pdu_key_t));
    CTC_CLI_GET_UINT8_RANGE("index", index, argv[0], 0, CTC_MAX_UINT8_VALUE);

    l2pdu_type = CTC_PDU_L2PDU_TYPE_MACDA;

    ret = ctcs_l2pdu_get_classified_key(g_api_lchip, l2pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("mac:%.2x%.2x.%.2x%.2x.%.2x%.2x\n", entry.l2pdu_by_mac.mac[0], entry.l2pdu_by_mac.mac[1],
                entry.l2pdu_by_mac.mac[2], entry.l2pdu_by_mac.mac[3], entry.l2pdu_by_mac.mac[4], entry.l2pdu_by_mac.mac[5]);

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_pdu_l2_classify_l2pdu_by_l2hdr_proto,
        ctc_cli_asw_pdu_l2_classify_l2pdu_by_l2hdr_proto_cmd,
        "pdu l2pdu classify l2hdr-proto index  INDEX  l2hdr-proto L2_HDR_PROTO",
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Classify pdu based on type",
        "Base on layer2 header protocol",
        "Entry index",
        "Index value",
        "Layer2 header protocol",
        "<0x0 - 0xFFFF>")
{
    ctc_pdu_l2pdu_key_t entry;
    ctc_pdu_l2pdu_type_t l2pdu_type;

    uint8 index = 0;
    int32 ret = 0;
    uint16 l2hdr_proto = 0;

    sal_memset(&entry, 0, sizeof(ctc_pdu_l2pdu_key_t));
    l2pdu_type = CTC_PDU_L2PDU_TYPE_L2HDR_PROTO;
    CTC_CLI_GET_UINT8_RANGE("index", index, argv[0], 0, CTC_MAX_UINT8_VALUE);
    CTC_CLI_GET_UINT16_RANGE("l2 hdr ptl", l2hdr_proto, argv[1], 0, CTC_MAX_UINT16_VALUE);

    entry.l2hdr_proto = l2hdr_proto;

    ret = ctcs_l2pdu_classify_l2pdu(g_api_lchip, l2pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_asw_pdu_show_l2_classify_l2pdu_by_l2hdr_proto,
        ctc_cli_asw_pdu_show_l2_classify_l2pdu_by_l2hdr_proto_cmd,
        "show pdu l2pdu classify l2hdr-proto index INDEX",
        CTC_CLI_SHOW_STR,
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Classify pdu based on type",
        "Layer2 header protocol",
        "Entry index",
        "Index value")
{
    ctc_pdu_l2pdu_type_t l2pdu_type;
    ctc_pdu_l2pdu_key_t entry;
    uint8 index = 0;
    int32 ret = 0;

    sal_memset(&entry, 0, sizeof(ctc_pdu_l2pdu_key_t));
    CTC_CLI_GET_UINT8_RANGE("index", index, argv[0], 0, CTC_MAX_UINT8_VALUE);

    l2pdu_type = CTC_PDU_L2PDU_TYPE_L2HDR_PROTO;

    ret = ctcs_l2pdu_get_classified_key(g_api_lchip, l2pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("Layer2 header protocol:0x%x\n", entry.l2hdr_proto);

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_pdu_l2_set_global_action_by_macda,
        ctc_cli_asw_pdu_l2_set_global_action_by_macda_cmd,
        "pdu l2pdu global-action macda-48bit index INDEX entry-valid ENTRY_VALID",
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Global action",
        "Base on 48bit Macda",
        "Entry index",
        CTC_CLI_L2PDU_MACDA_48BIT_ENTRY_INDEX,
        "Entry valid",
        "<0-0xFF>,when great than 1,as 1 to process")
{
    int32 ret = 0;
    uint8 index = 0;
    ctc_pdu_global_l2pdu_action_t entry;
    ctc_pdu_l2pdu_type_t l2pdu_type;

    sal_memset(&entry, 0, sizeof(ctc_pdu_global_l2pdu_action_t));

    l2pdu_type = CTC_PDU_L2PDU_TYPE_MACDA;
    CTC_CLI_GET_UINT8_RANGE("index", index, argv[0], 0, CTC_MAX_UINT8_VALUE);
    CTC_CLI_GET_UINT8_RANGE("entry valid", entry.entry_valid, argv[1], 0, CTC_MAX_UINT8_VALUE);

    ret = ctcs_l2pdu_set_global_action(g_api_lchip, l2pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_asw_pdu_l2_set_global_action_by_l2hdr_proto,
        ctc_cli_asw_pdu_l2_set_global_action_by_l2hdr_proto_cmd,
        "pdu l2pdu global-action l2hdr-proto index INDEX entry-valid ENTRY_VALID",
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Global action",
        "Base on layer2 header protocol",
        "Entry index",
        "Index value",
        "Entry valid",
        "<0-0xFF>,when great than 1,as 1 to process")
{
    int32 ret = 0;
    uint8 index = 0;
    ctc_pdu_global_l2pdu_action_t entry;
    ctc_pdu_l2pdu_type_t l2pdu_type;

    sal_memset(&entry, 0, sizeof(ctc_pdu_global_l2pdu_action_t));

    l2pdu_type = CTC_PDU_L2PDU_TYPE_L2HDR_PROTO;
    CTC_CLI_GET_UINT8_RANGE("index", index, argv[0], 0, CTC_MAX_UINT8_VALUE);
    CTC_CLI_GET_UINT8_RANGE("entry valid", entry.entry_valid, argv[1], 0, CTC_MAX_UINT8_VALUE);
    ret = ctcs_l2pdu_set_global_action(g_api_lchip, l2pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_pdu_show_l2_global_action,
        ctc_cli_asw_pdu_show_l2_global_action_cmd,
        "show pdu l2pdu global-action \
        (macda-48bit index INDEX|l2hdr-proto index INDEX)",
        CTC_CLI_SHOW_STR,
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Global action",
        "Base on 48bit Macda",
        "Entry index",
        "Index value",
        "Base on layer2 header protocol",
        "Entry index",
        "Index value")
{
    ctc_pdu_l2pdu_type_t l2pdu_type = MAX_CTC_PDU_L2PDU_TYPE;
    ctc_pdu_global_l2pdu_action_t entry;
    uint8 index = 0;
    int32 ret = 0;

    sal_memset(&entry, 0, sizeof(ctc_pdu_global_l2pdu_action_t));

    if (0 == sal_memcmp("macda-48bit", argv[0], sal_strlen("macda-48bit")))
    {
        l2pdu_type = CTC_PDU_L2PDU_TYPE_MACDA;
        CTC_CLI_GET_UINT8_RANGE("index", index, argv[2], 0, CTC_MAX_UINT8_VALUE);
    }

    if (0 == sal_memcmp("l2hdr-proto", argv[0], sal_strlen("l2hdr-proto")))
    {
        l2pdu_type = CTC_PDU_L2PDU_TYPE_L2HDR_PROTO;
        CTC_CLI_GET_UINT8_RANGE("index", index, argv[2], 0, CTC_MAX_UINT8_VALUE);
    }


    ret = ctcs_l2pdu_get_global_action(g_api_lchip, l2pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("entry_valid:0x%x\n", entry.entry_valid);
    ctc_cli_out("copy_to_cpu:0x%x\n", entry.copy_to_cpu);
    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_pdu_l2_set_port_action,
        ctc_cli_asw_pdu_l2_set_port_action_cmd,
        "pdu l2pdu port-action port PORT action-index ACTION_INDEX action-type (forward|copy-to-cpu|redirect-to-cpu|discard)",
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Per-port l2pdu action",
        "Port",
        CTC_CLI_GPHYPORT_ID_DESC,
        "Per-port action index",
        CTC_CLI_L2PDU_PER_PORT_ACTION_INDEX,
        "Action type",
        "Forward packet",
        "Forward and send to cpu",
        "Direct to cpu",
        "Discard packet")
{
    ctc_pdu_port_l2pdu_action_t action = MAX_CTC_PDU_L2PDU_ACTION_TYPE;
    uint8 action_index = 0;
    int32 ret = 0;

    uint16 gport = 0;

    CTC_CLI_GET_UINT16_RANGE("gport", gport, argv[0], 0, CTC_MAX_UINT16_VALUE);
    CTC_CLI_GET_UINT8_RANGE("action index", action_index, argv[1], 0, CTC_MAX_UINT8_VALUE);
    if (0 == sal_memcmp("forward", argv[2], 7))
    {
        action = CTC_PDU_L2PDU_ACTION_TYPE_FWD;
    }

    if (0 == sal_memcmp("copy", argv[2], 4))
    {
        action = CTC_PDU_L2PDU_ACTION_TYPE_COPY_TO_CPU;
    }

    if (0 == sal_memcmp("redirect", argv[2], 8))
    {
        action = CTC_PDU_L2PDU_ACTION_TYPE_REDIRECT_TO_CPU;
    }

    if (0 == sal_memcmp("discard", argv[2], 7))
    {
        action = CTC_PDU_L2PDU_ACTION_TYPE_DISCARD;
    }

    ret = ctcs_l2pdu_set_port_action(g_api_lchip, gport, action_index, action);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_asw_pdu_show_l2_port_action,
        ctc_cli_asw_pdu_show_l2_port_action_cmd,
        "show pdu l2pdu port-action port GPORT_ID action-index ACTION_INDEX action-type",
        CTC_CLI_SHOW_STR,
        CTC_CLI_PDU_STR,
        CTC_CLI_L2_PDU_STR,
        "Per-port l2pdu action",
        "Port",
        CTC_CLI_GPHYPORT_ID_DESC,
        "Per-port action index",
        CTC_CLI_L2PDU_PER_PORT_ACTION_INDEX,
        "Action type")
{
    ctc_pdu_port_l2pdu_action_t action;
    uint8 action_index = 0;
    int32 ret = 0;
    uint16 gport = 0;

    CTC_CLI_GET_UINT16_RANGE("gport", gport, argv[0], 0, CTC_MAX_UINT16_VALUE);
    CTC_CLI_GET_UINT8_RANGE("action index", action_index, argv[1], 0, CTC_MAX_UINT8_VALUE);

    ret = ctcs_l2pdu_get_port_action(g_api_lchip, gport, action_index, &action);

    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    if (action == CTC_PDU_L2PDU_ACTION_TYPE_REDIRECT_TO_CPU)
    {
        ctc_cli_out(" gport:0x%04x action index:%d action:%s  \n", gport, action_index, "redirect to cpu");
    }
    else if (action == CTC_PDU_L2PDU_ACTION_TYPE_COPY_TO_CPU)
    {
        ctc_cli_out("gport:0x%04x action index:%d action:%s  \n", gport, action_index, "copy to cpu");
    }
    else if (action == CTC_PDU_L2PDU_ACTION_TYPE_FWD)
    {
        ctc_cli_out(" gport:0x%04x action index:%d action:%s  \n", gport, action_index, "normal forwarding");
    }
    else if (action == CTC_PDU_L2PDU_ACTION_TYPE_DISCARD)
    {
        ctc_cli_out(" gport:0x%04x action index:%d action:%s  \n", gport, action_index, "discard ");
    }

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_asw_pdu_l3_classify_l3pdu_by_l3proto,
        ctc_cli_asw_pdu_l3_classify_l3pdu_by_l3proto_cmd,
        "pdu l3pdu classify layer3-proto index INDEX layer3-proto LAYER3_PROTO",
        CTC_CLI_PDU_STR,
        CTC_CLI_L3_PDU_STR,
        "Classify pdu base on layer3 protocol",
        "Base on layer3 protocol",
        "Entry index",
        CTC_CLI_L3PDU_ENTRY_INDEX,
        "Layer3 header protocol",
        "<0-255>")
{
    ctc_pdu_l3pdu_key_t entry;
    ctc_pdu_l3pdu_type_t l3pdu_type;

    uint8 index = 0;
    int32 ret = 0;
    uint8 l3hdr_proto = 0;

    sal_memset(&entry, 0, sizeof(ctc_pdu_l3pdu_key_t));
    l3pdu_type = CTC_PDU_L3PDU_TYPE_L3HDR_PROTO;
    CTC_CLI_GET_UINT8_RANGE("index", index, argv[0], 0, CTC_MAX_UINT8_VALUE);

    CTC_CLI_GET_UINT8_RANGE("l3 hdr ptl", l3hdr_proto, argv[1], 0, CTC_MAX_UINT8_VALUE);
    entry.l3hdr_proto = l3hdr_proto;

    ret = ctcs_l3pdu_classify_l3pdu(g_api_lchip, l3pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_asw_pdu_l3_classify_l3pdu_by_l4port,
        ctc_cli_asw_pdu_l3_classify_l3pdu_by_l4port_cmd,
        "pdu l3pdu classify layer4-port index INDEX is-udp UDP_EN_VAL is-tcp TCP_EN_VAL destport DESTPORT",
        CTC_CLI_PDU_STR,
        CTC_CLI_L3_PDU_STR,
        "Classify pdu based on layer3 protocol",
        "Layer4 port",
        "Entry index",
        CTC_CLI_L3PDU_ENTRY_INDEX,
        "Udp packet",
        "<0-0xFF>,when great than 1,as 1 to process",
        "Tcp packet",
        "<0-0xFF>,when great than 1,as 1 to process",
        "Layer4 dest port",
        "<0-0xFFFF>")
{
    ctc_pdu_l3pdu_key_t entry;
    ctc_pdu_l3pdu_type_t l3pdu_type;

    uint8 index = 0;
    int32 ret = 0;

    sal_memset(&entry, 0, sizeof(ctc_pdu_l3pdu_key_t));
    l3pdu_type = CTC_PDU_L3PDU_TYPE_LAYER4_PORT;
    CTC_CLI_GET_UINT8_RANGE("index", index, argv[0], 0, CTC_MAX_UINT8_VALUE);
    CTC_CLI_GET_UINT8_RANGE("is udp", entry.l3pdu_by_port.is_udp, argv[1], 0, CTC_MAX_UINT8_VALUE);
    CTC_CLI_GET_UINT8_RANGE("is tcp", entry.l3pdu_by_port.is_tcp, argv[2], 0, CTC_MAX_UINT8_VALUE);
    CTC_CLI_GET_UINT16_RANGE("l4-dest-port", entry.l3pdu_by_port.dest_port, argv[3], 0, CTC_MAX_UINT16_VALUE);

    ret = ctcs_l3pdu_classify_l3pdu(g_api_lchip, l3pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_asw_pdu_show_l3_classify_l3pdu,
        ctc_cli_asw_pdu_show_l3_classify_l3pdu_cmd,
        "show pdu l3pdu classify (layer3-proto|layer4-port) index INDEX",
        CTC_CLI_SHOW_STR,
        CTC_CLI_PDU_STR,
        CTC_CLI_L3_PDU_STR,
        "Classify pdu based on layer3 protocol",
        "Layer3 protocol",
        "Layer4 port",
        "Entry index",
        CTC_CLI_L3PDU_ENTRY_INDEX)
{
    ctc_pdu_l3pdu_key_t entry;
    ctc_pdu_l3pdu_type_t l3pdu_type = MAX_CTC_PDU_L3PDU_TYPE;

    uint8 index = 0;
    int32 ret = 0;

    sal_memset(&entry, 0, sizeof(ctc_pdu_l3pdu_key_t));

    if (0 == sal_memcmp("layer3-proto", argv[0], sal_strlen("layer3-proto")))
    {
        l3pdu_type = CTC_PDU_L3PDU_TYPE_L3HDR_PROTO;
    }

    if (0 == sal_memcmp("layer4-port", argv[0], sal_strlen("layer4-port")))
    {
        l3pdu_type = CTC_PDU_L3PDU_TYPE_LAYER4_PORT;
    }

    CTC_CLI_GET_UINT8_RANGE("index", index, argv[1], 0, CTC_MAX_UINT8_VALUE);

    ret = ctcs_l3pdu_get_classified_key(g_api_lchip, l3pdu_type, index, &entry);
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    if (0 == sal_memcmp("layer3-proto", argv[0], sal_strlen("layer3-proto")))
    {
        ctc_cli_out("l3hdr_proto:0x%x\n", entry.l3hdr_proto);
    }

    if (0 == sal_memcmp("layer4-port", argv[0], sal_strlen("layer4-port")))
    {
        ctc_cli_out("is_tcp_val:0x%x\n", entry.l3pdu_by_port.is_tcp);
        ctc_cli_out("is_udp_val:0x%x\n", entry.l3pdu_by_port.is_udp);
        ctc_cli_out("dest_port:0x%x\n", entry.l3pdu_by_port.dest_port);
    }

    if (0 == sal_memcmp("ipda", argv[0], sal_strlen("ipda")))
    {
        ctc_cli_out("\n");
        ctc_cli_out(" Item         Value\n");
        ctc_cli_out(" ------------------\n");
        ctc_cli_out(" IsIPv4       %u\n", entry.l3pdu_by_ipda.is_ipv4);
        ctc_cli_out(" IsIPv6       %u\n", entry.l3pdu_by_ipda.is_ipv6);
        ctc_cli_out(" IPDA         %u\n", entry.l3pdu_by_ipda.ipda);
        ctc_cli_out(" ActionIndex  %u\n\n", index);
    }

    return CLI_SUCCESS;

}

int32
ctc_asw_pdu_cli_init(uint8 cli_tree_mode)
{
    /*layer2 pdu cmd*/
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_l2_classify_l2pdu_by_macda_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_show_l2_classify_l2pdu_by_macda_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_l2_classify_l2pdu_by_l2hdr_proto_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_show_l2_classify_l2pdu_by_l2hdr_proto_cmd);

    install_element(cli_tree_mode, &ctc_cli_asw_pdu_l2_set_global_action_by_macda_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_l2_set_global_action_by_l2hdr_proto_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_show_l2_global_action_cmd);

    install_element(cli_tree_mode, &ctc_cli_asw_pdu_l2_set_port_action_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_show_l2_port_action_cmd);

    install_element(cli_tree_mode, &ctc_cli_asw_pdu_l3_classify_l3pdu_by_l3proto_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_l3_classify_l3pdu_by_l4port_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_pdu_show_l3_classify_l3pdu_cmd);

    return 0;
}

